@file:Suppress("SpellCheckingInspection")

package han.cirno.corrupt.components.school.impl.mju

import han.cirno.corrupt.data.instances.UserClassesData
import han.cirno.corrupt.data.instances.UserSchoolData
import han.cirno.corrupt.components.school.SchoolImpl
import han.cirno.corrupt.components.school.SchoolProvider
import han.cirno.corrupt.util.RegexUtil
import han.cirno.corrupt.util.fit
import org.json.JSONArray
import org.json.JSONObject

object MjuClassResolver {
    fun analyze(jsonText: String, xnm: String, xqm: String):UserClassesData.ClassTable{
        val jsonObject = JSONObject(jsonText)
        val kbArray = jsonObject["kbList"] as JSONArray
        val personalInfoObject = jsonObject["xsxx"] as JSONObject
        val classTable=UserClassesData.ClassTable(xnm,xqm)
        SchoolImpl.getImpl(UserSchoolData.School.MJU)?.dataOperation()
            ?.write(SchoolProvider.KEY_USERNAME,personalInfoObject["XM"].toString())
            ?.save()
        for (i in 0 until kbArray.length()){
            val classEntry=kbArray[i]
            classEntry as JSONObject
            val place="${classEntry["xqmc"]} ${classEntry["cdmc"]}"
            val name=classEntry["kcmc"].toString()
            val teacher=classEntry["xm"].toString()
            val weeksString=classEntry["zcd"].toString()
            val timeString=classEntry["jc"].toString()
            val dow=classEntry["xqjmc"].toString()
            classTable.classEntries.add(
                UserClassesData.ClassEntry(
                    "$xnm:$xqm",
                    name,
                    teacher,
                    getDow(dow),
                    getWeeks(weeksString),
                    getTimeRange(timeString),
                    place))
        }
        return classTable
    }

    private fun getWeeks(weeks:String):IntArray{
        val weeksSplit = weeks.split(",")
        val weeksList =HashSet<Int>()
        weeksSplit.forEach {
            val rangeMatch = RegexUtil.matchFirst(".*?(?=周)", it)
            if(rangeMatch!=null){
                val fromToWeeks = rangeMatch.split( "-")
                val intRange =
                    if (fromToWeeks.size==2)
                        IntRange(fromToWeeks[0].toInt(), fromToWeeks[1].toInt())
                    else
                        IntRange(fromToWeeks[0].toInt(),fromToWeeks[0].toInt())
                weeksList.addAll(intRange)
            }
            val iterator = weeksList.iterator()
            if(it.contains("单"))
                for (week in iterator)
                    if(week%2==0)iterator.remove()
            if (it.contains("双"))
                for (week in iterator)
                    if(week%2!=0)iterator.remove()
        }
        return weeksList.toIntArray()
    }

    private fun getDow(dowString:String): UserClassesData.DayOfWeek {
        return when{
            dowString.contains("一")-> UserClassesData.DayOfWeek.Mon
            dowString.contains("二")-> UserClassesData.DayOfWeek.Tue
            dowString.contains("三")-> UserClassesData.DayOfWeek.Wed
            dowString.contains("四")-> UserClassesData.DayOfWeek.Thur
            dowString.contains("五")-> UserClassesData.DayOfWeek.Fri
            dowString.contains("六")-> UserClassesData.DayOfWeek.Sat
            dowString.contains("日")-> UserClassesData.DayOfWeek.Sun
            else->throw IllegalArgumentException("Not a valid value!")
        }
    }

    private fun getTimeRange(timeString:String): UserClassesData.TimeRange {
        val timeMatch = RegexUtil.matchFirst(".*?(?=节)", timeString)?:throw IllegalArgumentException("Not a valid time string")
        val timesRange = timeMatch.split("-")
        return UserClassesData.TimeRange(
            (timesRange[0].toInt() - 1).fit(0..<MjuSchool.mjuClassTime.getSerialLength()),
            (timesRange[1].toInt() - 1).fit(0..<MjuSchool.mjuClassTime.getSerialLength())
        )
    }
}